package com.eshop.modules.system.service.impl;

import java.lang.invoke.SerializedLambda;
import java.util.Collection;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.eshop.utils.ValidationUtil;
import java.util.Set;
import com.eshop.modules.system.domain.Role;
import com.eshop.modules.system.domain.UsersRoles;
import com.eshop.exception.EntityExistException;
import java.io.File;
import com.eshop.utils.StringUtils;
import com.eshop.modules.system.domain.UserAvatar;
import com.eshop.utils.SecurityUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.web.multipart.MultipartFile;
import cn.hutool.core.date.DateUtil;
import java.util.Date;
import com.eshop.api.EshopException;
import java.io.IOException;
import com.eshop.utils.FileUtil;
import java.util.ArrayList;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import com.eshop.modules.system.domain.Dept;
import java.io.Serializable;
import com.eshop.modules.system.domain.Job;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.eshop.common.utils.QueryHelpPlus;
import com.eshop.modules.system.service.dto.UserDto;
import java.util.LinkedHashMap;
import java.util.List;
import com.github.pagehelper.PageInfo;
import java.util.Map;
import org.springframework.data.domain.Pageable;
import com.eshop.modules.system.service.dto.UserQueryCriteria;
import com.eshop.modules.system.service.UsersRolesService;
import com.eshop.utils.RedisUtils;
import com.eshop.modules.system.service.mapper.RoleMapper;
import com.eshop.modules.system.service.DeptService;
import com.eshop.modules.system.service.JobService;
import com.eshop.modules.system.service.UserAvatarService;
import com.eshop.dozer.service.IGenerator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;
import com.eshop.modules.system.service.UserService;
import com.eshop.modules.system.domain.User;
import com.eshop.modules.system.service.mapper.SysUserMapper;
import com.eshop.common.service.impl.BaseServiceImpl;

@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = { Exception.class })
public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, User> implements UserService
{
    @Value("${file.avatar}")
    private String avatar;
    private final IGenerator generator;
    private final SysUserMapper userMapper;
    private final UserAvatarService userAvatarService;
    private final JobService jobService;
    private final DeptService deptService;
    private final RoleMapper roleMapper;
    private final RedisUtils redisUtils;
    private final UsersRolesService usersRolesService;
    
    public SysUserServiceImpl(final IGenerator generator, final SysUserMapper userMapper, final UserAvatarService userAvatarService, final JobService jobService, final DeptService deptService, final RoleMapper roleMapper, final RedisUtils redisUtils, final UsersRolesService usersRolesService) {
        this.generator = generator;
        this.userMapper = userMapper;
        this.userAvatarService = userAvatarService;
        this.jobService = jobService;
        this.deptService = deptService;
        this.roleMapper = roleMapper;
        this.redisUtils = redisUtils;
        this.usersRolesService = usersRolesService;
    }
    
    public Map<String, Object> queryAll(final UserQueryCriteria criteria, final Pageable pageable) {
        this.getPage(pageable);
        final PageInfo<User> page = (PageInfo<User>)new PageInfo((List)this.queryAll(criteria));
        final Map<String, Object> map = new LinkedHashMap<String, Object>(2);
        map.put("content", this.generator.convert(page.getList(), (Class)UserDto.class));
        map.put("totalElements", page.getTotal());
        return map;
    }
    
    public List<User> queryAll(final UserQueryCriteria criteria) {
        final List<User> userList = (List<User>)((SysUserMapper)this.baseMapper).selectList(QueryHelpPlus.getPredicate(User.class, criteria));
        for (final User user : userList) {
            user.setJob((Job)this.jobService.getById((Serializable)user.getJobId()));
            user.setDept((Dept)this.deptService.getById((Serializable)user.getDeptId()));
            user.setRoles(this.roleMapper.findByUsers_Id(user.getId()));
        }
        return userList;
    }
    
    public void download(final List<UserDto> all, final HttpServletResponse response) throws IOException {
        final List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for (final UserDto user : all) {
            final Map<String, Object> map = new LinkedHashMap<String, Object>();
            map.put("邮箱", user.getEmail());
            map.put("状态：1启用、0禁用", user.getEnabled());
            map.put("密码", user.getPassword());
            map.put("用户名", user.getUsername());
            map.put("部门名称", user.getDeptId());
            map.put("手机号码", user.getPhone());
            map.put("创建日期", user.getCreateTime());
            map.put("最后修改密码的日期", user.getLastPasswordResetTime());
            map.put("昵称", user.getNickName());
            map.put("性别", user.getSex());
            list.add(map);
        }
        FileUtil.downloadExcel((List)list, response);
    }
    
    public UserDto findByName(final String userName) {
        final User user = this.userMapper.findByName(userName);
        if (user == null) {
            throw new EshopException("当前用户不存在");
        }
        user.setJob((Job)this.jobService.getById((Serializable)user.getJobId()));
        user.setDept((Dept)this.deptService.getById((Serializable)user.getDeptId()));
        return (UserDto)this.generator.convert(user, (Class)UserDto.class);
    }
    
    public void updatePass(final String username, final String encryptPassword) {
        this.userMapper.updatePass(encryptPassword, DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), username);
    }
    
    public void updateAvatar(final MultipartFile multipartFile) {
        final User user = this.getOne( Wrappers.<User>lambdaQuery().eq(User::getUsername, SecurityUtils.getUsername()));
        UserAvatar userAvatar = (UserAvatar)this.userAvatarService.getOne(Wrappers.<UserAvatar>lambdaQuery().eq(UserAvatar::getId, user.getAvatarId()));
        String oldPath = "";
        if (userAvatar != null) {
            oldPath = userAvatar.getPath();
        }
        else {
            userAvatar = new UserAvatar();
        }
        final File file = FileUtil.upload(multipartFile, this.avatar);
        assert file != null;
        userAvatar.setRealName(file.getName());
        userAvatar.setPath(file.getPath());
        userAvatar.setSize(FileUtil.getSize(multipartFile.getSize()));
        this.userAvatarService.saveOrUpdate(userAvatar);
        user.setAvatarId(userAvatar.getId());
        this.saveOrUpdate(user);
        if (StringUtils.isNotBlank((CharSequence)oldPath)) {
            FileUtil.del(oldPath);
        }
    }
    
    public void updateEmail(final String username, final String email) {
        this.userMapper.updateEmail(email, username);
    }
    
    @Transactional(rollbackFor = { Exception.class })
    public boolean create(final User resources) {
        final User userName = this.getOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, resources.getUsername()));
        if (userName != null) {
            throw new EntityExistException((Class)User.class, "username", resources.getUsername());
        }
        final User userEmail = this.getOne(Wrappers.<User>lambdaQuery().eq(User::getEmail, resources.getEmail()));
        if (userEmail != null) {
            throw new EntityExistException((Class)User.class, "email", resources.getEmail());
        }
        resources.setDeptId(resources.getDept().getId());
        resources.setJobId(resources.getJob().getId());
        final boolean result = this.save(resources);
        final UsersRoles usersRoles = new UsersRoles();
        usersRoles.setUserId(resources.getId());
        final Set<Role> set = resources.getRoles();
        for (final Role roleIds : set) {
            usersRoles.setRoleId(roleIds.getId());
        }
        if (result) {
            this.usersRolesService.save(usersRoles);
        }
        return result;
    }
    
    @Transactional(rollbackFor = { Exception.class })
    public void update(final User resources) {
        final User user = this.getOne(Wrappers.<User>lambdaQuery().eq(User::getId, resources.getId()));
        ValidationUtil.isNull(user.getId(), "User", "id", resources.getId());
        final User user2 = this.getOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, resources.getUsername()));
        final User user3 = this.getOne(Wrappers.<User>lambdaQuery().eq(User::getEmail, resources.getEmail()));
        if (user2 != null && !user.getId().equals(user2.getId())) {
            throw new EntityExistException((Class)User.class, "username", resources.getUsername());
        }
        if (user3 != null && !user.getId().equals(user3.getId())) {
            throw new EntityExistException((Class)User.class, "email", resources.getEmail());
        }
        user.setUsername(resources.getUsername());
        user.setEmail(resources.getEmail());
        user.setEnabled(resources.getEnabled());
        user.setDeptId(resources.getDept().getId());
        user.setJobId(resources.getJob().getId());
        user.setPhone(resources.getPhone());
        user.setNickName(resources.getNickName());
        user.setSex(resources.getSex());
        final boolean result = this.saveOrUpdate(user);
        ((LambdaUpdateChainWrapper)this.usersRolesService.lambdaUpdate().eq(UsersRoles::getUserId, resources.getId())).remove();
        final UsersRoles usersRoles = new UsersRoles();
        usersRoles.setUserId(resources.getId());
        final Set<Role> set = resources.getRoles();
        for (final Role roleIds : set) {
            usersRoles.setRoleId(roleIds.getId());
        }
        if (result) {
            this.usersRolesService.save(usersRoles);
        }
        if (!resources.getRoles().equals(user.getRoles())) {
            String key = "role::loadPermissionByUser:" + user.getUsername();
            this.redisUtils.del(new String[] { key });
            key = "role::findByUsers_Id:" + user.getId();
            this.redisUtils.del(new String[] { key });
        }
    }
    
    @Transactional(rollbackFor = { Exception.class })
    public void delete(final Set<Long> ids) {
        for (final Long id : ids) {
            ((LambdaUpdateChainWrapper)this.usersRolesService.lambdaUpdate().eq(UsersRoles::getUserId, id)).remove();
        }
        this.removeByIds((Collection)ids);
    }
}
